package se.sll.itintegration.catalogue.product.ejb;

import java.util.ArrayList;
import java.util.List;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import lombok.extern.slf4j.Slf4j;
import se.sll.itintegration.catalogue.product.entity.CodeEntity;
import se.sll.service.catalogue.common.AbstractJpaFacade;
import se.sll.service.catalogue.common.exception.BusinessLogicException;
import se.sll.service.catalogue.common.rest.response.CodeResponse;

/**
 *
 * @author khaleddaham
 */
@Slf4j
@Stateless
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public class CodeEjb extends AbstractJpaFacade<CodeEntity> {

    @PersistenceContext(unitName = "productPU")
    private EntityManager em;

    @Override
    protected EntityManager getEntityManager() {
        return em;
    }

    @Override
    protected void setEntityManager(EntityManager em) {
        this.em = em;
    }

    /**
     *
     */
    public CodeEjb() {
        super(CodeEntity.class);
    }

    /**
     *
     * @param name
     * @return
     */
    public List<CodeEntity> findByName(String name) {
        log.debug("ProductEjb.findByName() was called");
        return super.findByAttributeValue("code", name);
    }

    /**
     *
     * @param description
     * @return
     */
    public List<CodeEntity> findByDescription(String description) {
        log.debug("ProductEjb.findByDescription() was called");
        TypedQuery<CodeEntity> query = getEntityManager().createNamedQuery(CodeEntity.QUERY_DESCRIPTION_LIKE, CodeEntity.class);
        query.setParameter("description", "%" + description + "%");
        return query.getResultList();
    }

    /**
     *
     * @param description
     * @return
     */
    public List<CodeEntity> findByDisplayName(String displayName) {
        log.debug("CodeEjb.findByDisplayName() was called");
        TypedQuery<CodeEntity> query = getEntityManager().createNamedQuery(CodeEntity.QUERY_DISPLAYNAME_LIKE, CodeEntity.class);
        query.setParameter("displayname", "%" + displayName + "%");
        return query.getResultList();
    }

    /**
     * Finds a unique code if it exists
     *
     * @param oid
     * @param code
     * @return The <code>CodeEntity</code> if it exists, <code>null</code> if
     * not found, or <code>BusinessLogicException</code> if multiple codes are
     * found.
     */
    public CodeEntity findUniqueCode(String oid, String code) throws BusinessLogicException {
        log.debug("CodeSystemEjb.findUniqueCode() was called");
        TypedQuery<CodeEntity> q = getEntityManager().createNamedQuery(CodeEntity.QUERY_FINDBY_OID_AND_CODE, CodeEntity.class);
        q.setParameter("oid", oid);
        q.setParameter("code", code);

        List<CodeEntity> ceL = q.getResultList();

        CodeEntity ce = null;
        if (ceL != null) {
            switch (ceL.size()) {
                case 0: {
                    ce = null;
                    break;
                }
                case 1: {
                    ce = ceL.get(0);
                    break;
                }
                default: {
                    String msg = "Duplicate codes found: oid = " + oid + ", code = " + code;
                    log.error(msg);
                    throw new BusinessLogicException(msg);
                }
            }
        } else {
            throw new BusinessLogicException();
        }
        return ce;
    }

    /**
     * Return a list of codes for a given codesystem oid
     *
     * @param oid
     * @return
     */
    public List<CodeResponse> getCodeListByCodeSystem(String oid) {
        log.debug("getCodeListByCodeSystem for: " + oid);
        TypedQuery<CodeEntity> q = getEntityManager().createNamedQuery(CodeEntity.QUERY_FINDBY_OID, CodeEntity.class);
        q.setParameter("oid", oid);
        return returnCodes(q.getResultList(), oid);
    }

    private List<CodeResponse> returnCodes(List<CodeEntity> codeEntityList, String oid) {
        List<CodeResponse> responseList = new ArrayList<>();
        for (CodeEntity ce : codeEntityList) {
            CodeResponse cr = new CodeResponse();
            cr.setCode(ce.getCode());
            cr.setDescription(ce.getDescription());
            cr.setDisplayName(ce.getDisplayName());
            cr.setOid(oid);
            responseList.add(cr);
        }
        return responseList;
    }
}
